package com.lolaage.tracks;

import java.util.List;
import java.util.Vector;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;

import com.lolaage.tracks.adapter.MyBMapManager;
import com.lolaage.tracks.content.DB;
import com.lolaage.tracks.content.TrackProvider;

/*********************************************************
 * @author : zhaohua
 * @version : 2012-9-10
 * @see : 轨迹管理器
 * @Copyright : copyrights reserved by personal 2007-2011
 **********************************************************/
public class MyTrackManager
{
    private static final String TAG = "MyTrackClient";
    public static enum TRACK_STATE
    {
        STARTED,
        PAUSEED,
        STOPED
    }
    public static enum LOC_ENGINER
    {
        MYSLEF,
        BAIDU,
        NONE
    }
    private MyTrackService mTrackService;
    private TrackProvider  mTrackProder;
    private Vector<TrackListener> mTrackListners;
    private Context mContext;
    private Runnable mCallBack;
    private static int mClientId;
    
    private static MyTrackManager instance;
    private MyTrackManager(Context context,int clientId)
    {
        mContext = context;
        mClientId = clientId;
        mTrackProder = new TrackProvider(clientId);
        mTrackListners = new Vector<TrackListener>(5, 5);
        tryBindService(true);
    }
    
    public static MyTrackManager getInstance()
    {
        return instance;
    }
    
    public static MyTrackManager init(Context context,int clientId)
    {
        if(instance == null)
        {
            instance = new MyTrackManager(context,clientId);
            DB.initDB(context);
        }
        return instance;
    }
    
    public void start(final Runnable clientCallback)
    {
        if(!tryBindService(false))
        {
            mCallBack = new Runnable()
            {
                @Override
                public void run()
                {
                    mTrackService.addTrackListener(mRealTrackListener);
                    mTrackService.start();
                    if(clientCallback != null)
                    {
                        clientCallback.run();
                    }
                }
            };
            tryBindService(true);
        }else
        {
            mTrackService.addTrackListener(mRealTrackListener);
            mTrackService.start();
            if(clientCallback != null)
            {
                clientCallback.run();
            }
        }
    }
    
    public void startContinue(final Runnable clientCallback)
    {
        if(!tryBindService(false))
        {
            mCallBack = new Runnable()
            {
                @Override
                public void run()
                {
                    mTrackService.addTrackListener(mRealTrackListener);
                    mTrackService.startContinue();
                    if(clientCallback != null)
                    {
                        clientCallback.run();
                    }
                }
            };
            tryBindService(true);
        }else
        {
            mTrackService.addTrackListener(mRealTrackListener);
            mTrackService.startContinue();
            if(clientCallback != null)
            {
                clientCallback.run();
            }
        }
    }
    
    public void pause()
    {
        if(tryBindService(false))
        {
            mTrackService.pause();
        }
    }
    
    public void resume()
    {
        if(tryBindService(false))
        {
            mTrackService.resume();
        }
    }
    
    public void stop()
    {
        if(tryBindService(false))
        {
            mTrackService.rmvTrackListener(mRealTrackListener);
            mTrackService.stop();
            unBindService();
        }
    }
    
    public void destory()
    {
        mTrackListners.clear();
        DB.closeDB();
        MyBMapManager.getInstace(mContext).destory();
    }
    
    // 获取轨迹的状态
    public TRACK_STATE getState()
    {
        if(tryBindService(false))
        {
            return mTrackService.getState();
        }else
        {
            return TRACK_STATE.STOPED;
        }
    }
    
    // 获取轨迹的定位引擎类型
    public LOC_ENGINER getLocEnginerType()
    {
        if(tryBindService(false))
        {
            return mTrackService.getLocEnginerType();
        }else
        {
            return LOC_ENGINER.NONE;
        }
    }
    
    // 切换轨迹的定位引擎
    public boolean switchLocEnginer(LOC_ENGINER type)
    {
        if(tryBindService(false))
        {
            if(type == LOC_ENGINER.BAIDU)
            {
                mTrackService.initBaiduLocEnginer(false);
            }else
            {
                mTrackService.initSelfLocEnginer(false);
            }
            return true;
        }else
        {
            return false;
        }
    }
    
    public void registerTrackListener(TrackListener listner)
    {
        if(listner != null && !mTrackListners.contains(listner))
        {
            mTrackListners.add(listner);
        }       
    }
    
    public void unregisterTrackListener(TrackListener listner)
    {
        if(listner != null && mTrackListners.contains(listner))
        {
            mTrackListners.remove(listner);
        }
    }
    
    public boolean loadCurTrack()
    {        
        if(tryBindService(false))
        {
            long trackId = mTrackService.getCurTrackId();
            if( trackId > 0)
            {
                loadTrack(trackId);
                return true;
            }else
            {
                return false;
            }
        }else
        {
            return false;
        }
    }
    
    /** 载入轨迹，并通过监听器获取轨迹的节点信息*/
    public void loadTrack(final long trackid)
    {
        new AsyncTask<Void, Void, List<TrackPoint>>()
        {
            @Override
            protected List<TrackPoint> doInBackground(Void... params)
            {
                return mTrackProder.getPoints(trackid);
            }
            
            protected void onPostExecute(List<TrackPoint> result) 
            {
                mRealTrackListener.onTrackPointChanged(result);
            };
        }.execute();
    }
    
    private TrackListener mRealTrackListener = new TrackListener()
    {
        @Override
        public void onTrackPointChanged(List<TrackPoint> appendPoints)
        {
            for(TrackListener one : mTrackListners)
            {
                one.onTrackPointChanged(appendPoints);
            }
        }

        @Override
        public void onNewTrack(Track track)
        {
            for(TrackListener one : mTrackListners)
            {
                one.onNewTrack(track);
            }
        }
        
        public void onTrackUpdated(Track track) 
        {
            for(TrackListener one : mTrackListners)
            {
                one.onTrackUpdated(track);
            }
        };
    };
    /////////////////////////////////////////////////////////////////////////////////////////
    /** 连接服务*/
    private boolean mIsBound;
    
    private boolean tryBindService(boolean retryAble)
    {
        if(mIsBound && mTrackService != null)
        {
            return true;
        }
        
        if(retryAble)
        {
            bindService();
        }
        return false;
    }
    
    private void bindService()
    {        
        if( !mIsBound)
        {
            if(mTrackService == null)
            {
                mContext.bindService(new Intent(mContext, MyTrackService.class), mConnection, Context.BIND_AUTO_CREATE);
            }
            mIsBound = true;
        }
    }
    
    private void unBindService()
    {
        if( mIsBound )
        {
            if(mTrackService != null)
            {
                mContext.unbindService(mConnection);
            }
            mTrackService = null;
            mIsBound = false;
        }
    }
    
    private ServiceConnection mConnection = new ServiceConnection() 
    {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            mTrackService = ((MyTrackService.LocalBinder)service).getService(); 
            mTrackService.initCilent(mClientId);
            // 连接时回调
            if(mCallBack != null)
            {
                mCallBack.run();
            }
            Log.d(TAG, "service connected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            mTrackService = null;
            mCallBack = null;
            Log.d(TAG, "service disConnected");
        }
    };
    //////////////////////////////////////////////////////////////////////////////////////////
    /** 获取轨迹数据内容提供者*/
    public TrackProvider getTrackProvider()
    {
        return mTrackProder;
    }
}
